home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 March: Reference Library / Dev.CD Mar 96 RL / Dev.CD Mar 96 RL.toast / Technical Documentation / develop / develop Issue 25 / develop Issue 25 code / ToolFrontEnd / ToolFrontEnd Source / ToolFrontEnd Panel / ToolFrontEndPanel.c < prev   
Encoding:
C/C++ Source or Header  |  1995-12-19  |  30.6 KB  |  1,114 lines  |  [TEXT/CWIE]

  1. /*
  2.  *  ToolFrontEndPanel.c - ToolServer Front End Drop-In Preferences
  3.  */
  4.  
  5.  
  6. #define    BUILDING_FOR_SYSTEM7    1
  7.  
  8. /* standard headers */
  9. #include <stdarg.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12.  
  13. /* system headers */
  14. #include <AERegistry.h>
  15. #include <Resources.h>
  16. #include <TextUtils.h>
  17. #include <Controls.h>
  18. #include <LowMem.h>
  19.  
  20. /* compiler headers */
  21. #include <A4Stuff.h>
  22. #include <SetUpA4.h>
  23. #include <DropInPanel.h>
  24.  
  25. /* project headers */
  26. #include "ToolFrontEnd.h"
  27. #include "MoreFilesExtras.h"
  28.  
  29.  
  30. /* current version number for our prefs data */
  31. #define PTOOLFRONTENDVERSION 2
  32.  
  33.  
  34. enum {
  35.     kItemListID = 128,
  36.     kIncludeScannerItem = 1,
  37.     kIncludePathItem = 2,
  38.     kIncludeBoxItem = 5,
  39.     kCommandLabelItem = 6,
  40.     kCommandItem = 7,
  41.     kExtensionPopupItem = 8,
  42.     kScriptIncludeFileItem = 10,
  43.     kOverallBoxItem = 11,
  44.     kGetExtensionDialog = 129,
  45.     kExtensionTextItem = 4
  46. };
  47.  
  48.  
  49. typedef struct
  50. {
  51.     short current;                // current selection in popup menu
  52.     Boolean enableIncludes;        // scan for include files
  53.     Boolean popupsInitialized;    // has the popup been initialized?
  54. } ToolFrontEndPanelStatus;
  55.  
  56.  
  57. /* prototypes of local functions */
  58. static void*    InitDialog(DialogPtr dp, short baseItems);
  59. static void        TermDialog(DialogPtr dp, short baseItems, void *storage);
  60. static OSErr    OptionsToDialog(DialogPtr dp, Handle options, short baseItems, void *storage);
  61. static short    DialogToOptions(DialogPtr dp, Handle options, short baseItems, void *storage);
  62. static short    Filter(DialogPtr dp, EventRecord *event, short *itemHit, void *storage);
  63. static void        ItemHit(PanelParameterBlock *pb, void *storage);
  64. static void        Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset);
  65. static short    GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings);
  66. static short    SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings);
  67. static short    GetFactory(Handle settings, DialogPtr dp);
  68. static short    UpdatePref(Handle settings);
  69. static Boolean    ComparePrefs(Handle prefsHand1, Handle prefsHand2);
  70. static pascal void    PanelDrawIncludeBox(DialogPtr dp, short item);
  71. static pascal void    PanelDrawOverallBox(DialogPtr dp, short item);
  72. static Boolean    GetExtensionString(StringPtr extension);
  73. static void        EnableMainItems(DialogPtr dp, short baseItems);
  74. static void        DisableAllItems(DialogPtr dp, short baseItems);
  75. static void        EnableIncludeItems(DialogPtr dp, short baseItems);
  76. static void        DisableIncludeItems(DialogPtr dp, short baseItems);
  77. static void        FixEditField(DialogPtr dp);
  78.  
  79.  
  80. static void *theStorage = NULL; // for DrawUserItem
  81.  
  82. /*
  83.  *    main    -    entry-point for Drop-In Preferences Panel
  84.  *
  85.  */
  86.  
  87. pascal short main(PanelParameterBlock *pb)
  88. {
  89.     short err = noErr;
  90.     
  91.     EnterCodeResource();
  92.     PrepareCallback();
  93.     
  94.     switch (pb->request)
  95.     {
  96.     case reqInitPanel:
  97.         /* panel has just been loaded into memory */
  98.         theStorage = NULL;
  99.         break;
  100.  
  101.     case reqTermPanel:
  102.         /* panel is about to be unloaded from memory */
  103.         break;
  104.  
  105.     case reqInitDialog:
  106.         /* hook our dialog item list into the preferences dialog */
  107.         theStorage = pb->storage = InitDialog(pb->dialog, pb->baseItems);
  108.         break;
  109.         
  110.     case reqTermDialog:
  111.         /* unhook our dialog item list from the preferences dialog */
  112.         TermDialog(pb->dialog, pb->baseItems, pb->storage);
  113.         break;
  114.     
  115.     case reqPutData:
  116.         /* put the data in the given handle into our dialog items */
  117.         OptionsToDialog(pb->dialog, pb->currentPrefs, pb->baseItems, pb->storage);
  118.         break;
  119.  
  120.     case reqGetData:
  121.         /* fill in the given handle with our dialog items */
  122.         err = DialogToOptions(pb->dialog, pb->currentPrefs, pb->baseItems, pb->storage);
  123.         break;
  124.  
  125.     case reqFilter:
  126.         /* filter an event in the dialog */
  127.         err = Filter(pb->dialog, pb->event, &pb->itemHit, pb->storage);
  128.         break;
  129.         
  130.     case reqItemHit:
  131.         /* handle a hit on one of our dialog items */
  132.         ItemHit(pb, pb->storage);
  133.         break;
  134.         
  135.     case reqAEGetPref:
  136.         /* return one item in the given handle as an Apple Event descriptor */
  137.         err = GetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
  138.         break;
  139.  
  140.     case reqAESetPref:
  141.         /* change one item in the given handle according to the given Apple Event descriptor */
  142.         err = SetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
  143.         break;
  144.  
  145.     case reqValidate:
  146.         /* determine if we need to reset paths, recompile, or relink */
  147.         Validate(pb->originalPrefs, pb->currentPrefs, &pb->recompile, &pb->relink, &pb->reset);
  148.         break;
  149.  
  150.     case reqGetFactory:
  151.         /* return our factory settings */
  152.         err = GetFactory(pb->factoryPrefs, pb->dialog);
  153.         break;
  154.  
  155.     case reqUpdatePref:
  156.         /* update the given handle to use the current format for our prefs data */
  157.         err = UpdatePref(pb->currentPrefs);
  158.         break;
  159.         
  160.     default:
  161.         err = paramErr;
  162.         break;
  163.     }
  164.     
  165.     ExitCodeResource();
  166.     
  167.     return err;
  168. }
  169.  
  170.  
  171. /*
  172.  *    PanelDrawOverallBox  -    user item proc to draw box
  173.  */
  174.  
  175. static pascal void PanelDrawOverallBox(DialogPtr dp, short item)
  176. {
  177.     GrafPtr        savedPort;
  178.     PenState    savedPen;
  179.     Handle        itemHand;
  180.     short        itemType;
  181.     Rect        itemRect;
  182.     ToolFrontEndPanelStatus** status;
  183.     
  184.     EnterCallback();
  185.     
  186.     status = (ToolFrontEndPanelStatus**)theStorage;
  187.     
  188.     GetPort(&savedPort);
  189.     SetPort((GrafPtr)dp);
  190.     GetPenState(&savedPen);
  191.     PenNormal();
  192.     
  193.     GetDialogItem(dp, item, &itemType, &itemHand, &itemRect);
  194.     FrameRect(&itemRect);
  195.     
  196.     if (status != NULL && (*status)->current < 0)
  197.     {
  198.         // grey it out -- no extensions yet
  199.         Pattern gray;
  200.         short baseItems = item - kOverallBoxItem;
  201.         Rect labelRect;
  202.         
  203.         GetDialogItem(dp, baseItems + kCommandLabelItem, &itemType, &itemHand, &labelRect);
  204.         
  205.         GetIndPattern(&gray, sysPatListID, 4);
  206.         PenMode(patBic);
  207.         PenPat(&gray);
  208.         InsetRect(&itemRect, 1, 1);
  209.         itemRect.top = labelRect.top - 1;
  210.         PaintRect(&itemRect);
  211.     }
  212.     
  213.     SetPenState(&savedPen);
  214.     SetPort(savedPort);
  215.     
  216.     ExitCallback();
  217. }
  218.  
  219.  
  220. /*
  221.  *    PanelDrawIncludeBox  -    user item proc to draw box
  222.  */
  223.  
  224. static pascal void PanelDrawIncludeBox(DialogPtr dp, short item)
  225. {
  226.     GrafPtr        savedPort;
  227.     PenState    savedPen;
  228.     Handle        itemHand;
  229.     short        itemType;
  230.     Rect        itemRect;
  231.     ToolFrontEndPanelStatus** status;
  232.     
  233.     EnterCallback();
  234.     
  235.     status = (ToolFrontEndPanelStatus**)theStorage;
  236.     
  237.     GetPort(&savedPort);
  238.     SetPort((GrafPtr)dp);
  239.     GetPenState(&savedPen);
  240.     PenNormal();
  241.     
  242.     GetDialogItem(dp, item, &itemType, &itemHand, &itemRect);
  243.     FrameRect(&itemRect);
  244.     
  245.     if (status != NULL && (*status)->current >= 0 && !(*status)->enableIncludes)
  246.     {
  247.         // grey it out -- no include options
  248.         Pattern gray;
  249.         GetIndPattern(&gray, sysPatListID, 4);
  250.         PenMode(patBic);
  251.         PenPat(&gray);
  252.         InsetRect(&itemRect, 1, 1);
  253.         PaintRect(&itemRect);
  254.     }
  255.     
  256.     SetPenState(&savedPen);
  257.     SetPort(savedPort);
  258.     
  259.     ExitCallback();
  260. }
  261.  
  262.  
  263. /*
  264.  *    InitDialog  -    initialize Dialog Box items for this panel
  265.  *
  266.  */
  267.  
  268. static void *InitDialog(DialogPtr dp, short baseItems)
  269. {
  270.     ToolFrontEndPanelStatus**    status;
  271.     Handle                        itemHand, newItems;
  272.     short                        itemType;
  273.     Rect                        itemRect;
  274.     UserItemUPP                    drawBoxUPP;
  275.     
  276.     newItems = Get1Resource('DITL', kItemListID);
  277.     AppendDITL(dp, newItems, overlayDITL);
  278.     
  279.     drawBoxUPP = NewUserItemProc(PanelDrawIncludeBox);
  280.     GetDialogItem(dp, baseItems + kIncludeBoxItem, &itemType, &itemHand, &itemRect);
  281.     SetDialogItem(dp, baseItems + kIncludeBoxItem, itemType, (Handle) drawBoxUPP, &itemRect);
  282.     
  283.     drawBoxUPP = NewUserItemProc(PanelDrawOverallBox);
  284.     GetDialogItem(dp, baseItems + kOverallBoxItem, &itemType, &itemHand, &itemRect);
  285.     SetDialogItem(dp, baseItems + kOverallBoxItem, itemType, (Handle) drawBoxUPP, &itemRect);
  286.     
  287.     SelectDialogItemText(dp, baseItems + kCommandItem, 0, 32767);
  288.     
  289.     status = (ToolFrontEndPanelStatus**)NewHandleClear(sizeof(ToolFrontEndPanelStatus));
  290.     (*status)->current = -1;
  291.  
  292.     return (void*)status;
  293. }
  294.  
  295. /*
  296.  *    TermDialog    -    destroy Dialog Box items for this panel
  297.  *
  298.  */
  299.  
  300. static void TermDialog(DialogPtr dp, short baseItems, void *storage)
  301. {
  302.     short        itemType;
  303.     Rect        itemRect;
  304.     UserItemUPP    drawBoxUPP;
  305.     ToolFrontEndPanelStatus** status = (ToolFrontEndPanelStatus**)storage;
  306.     
  307.     GetDialogItem(dp, baseItems + kIncludeBoxItem, &itemType, (Handle *) &drawBoxUPP, &itemRect);
  308.     DisposeRoutineDescriptor(drawBoxUPP);
  309.     GetDialogItem(dp, baseItems + kOverallBoxItem, &itemType, (Handle *) &drawBoxUPP, &itemRect);
  310.     DisposeRoutineDescriptor(drawBoxUPP);
  311.     
  312.     if (status != NULL) DisposeHandle((Handle)status);
  313.     theStorage = NULL;
  314. }
  315.  
  316.  
  317. /*
  318.  *    OptionsToDialog        -    copy the options data from the handle to the screen
  319.  *
  320.  */
  321.  
  322. static OSErr OptionsToDialog(DialogPtr dp, Handle options, short baseItems, void *storage)
  323. {
  324.     ToolFrontEndPanelStatus**    status = (ToolFrontEndPanelStatus**)storage;
  325.     ToolFrontEndPrefHandle        prefsData = (ToolFrontEndPrefHandle) options;
  326.     Handle                        itemHand;
  327.     short                        itemType;
  328.     Rect                        itemRect;
  329.     Byte                        state;
  330.     int                            i;
  331.     MenuHandle                    menu;
  332.     ControlHandle                popup;
  333.     Handle                        controlData;
  334.     PopupPrivateDataHandle        popupData;
  335.     OSErr                        err;
  336.  
  337.     // initialize the popup menus
  338.     if (!(*status)->popupsInitialized)
  339.     {
  340.         // initialize the filename extensions popup
  341.         GetDialogItem(dp, baseItems + kExtensionPopupItem, &itemType, &itemHand, &itemRect);
  342.         popup = (ControlHandle)itemHand;
  343.         controlData = (*popup)->contrlData;
  344.         popupData = (PopupPrivateDataHandle)controlData;
  345.         menu = (*popupData)->mHandle;
  346.         DisableItem(menu, 2); // disable remove
  347.         while (CountMenuItems(menu) > 2) DeleteMenuItem(menu, 3);
  348.         SetControlMaximum(popup, 2);
  349.         (*status)->current = -1;
  350.     
  351.         for (i = 0; i < (*prefsData)->numExtensions; i++)
  352.         {
  353.             if (i == 0)
  354.             {
  355.                 AppendMenu(menu, "\p(-");    // separator line
  356.                 EnableItem(menu, 2);        // enable remove
  357.                 (*status)->current = 0;
  358.                 SetControlMaximum(popup, 3);
  359.             }
  360.             
  361.             state = HGetState(options);
  362.             HLock(options);
  363.             AppendMenu(menu, "\pgrog");
  364.             SetMenuItemText(menu, CountMenuItems(menu), (*prefsData)->extensions[i].extension);
  365.             SetControlMaximum(popup, GetControlMaximum(popup) + 1);
  366.             HSetState(options, state);
  367.             
  368.             if (i == 0)
  369.                 SetControlValue(popup, 4);    // select first extension
  370.         }
  371.         
  372.         // initialize the include file scanner popup
  373.         GetDialogItem(dp, baseItems + kIncludeScannerItem, &itemType, &itemHand, &itemRect);
  374.         popup = (ControlHandle)itemHand;
  375.         controlData = (*popup)->contrlData;
  376.         popupData = (PopupPrivateDataHandle)controlData;
  377.         menu = (*popupData)->mHandle;
  378.         
  379.         // find the include file scanner folder
  380.         {
  381.             Str31 folderName;
  382.             FCBPBRec pb;
  383.             CInfoPBRec ci;
  384.             FSSpec *scanners;
  385.             short actualCount;
  386.             short index;
  387.             
  388.             pb.ioFCBIndx = 0; // use ioRefNum
  389.             pb.ioRefNum = LMGetCurApRefNum();
  390.             pb.ioNamePtr = NULL;
  391.             err = PBGetFCBInfoSync(&pb);
  392.             if (err != noErr) return err;
  393.             GetIndString(folderName, 128, 1); // CodeWarrior Plugins
  394.             ci.dirInfo.ioNamePtr = folderName;
  395.             ci.dirInfo.ioVRefNum = pb.ioFCBVRefNum;
  396.             ci.dirInfo.ioDrDirID = pb.ioFCBParID;
  397.             ci.dirInfo.ioFDirIndex = 0;
  398.             err = PBGetCatInfoSync(&ci);
  399.             if (err != noErr) return err;
  400.             GetIndString(folderName, 128, 2); // Include Scanners
  401.  
  402.             // iterate over all files in folder, adding to popup menu
  403.             scanners = (FSSpec*)NewPtr(sizeof(FSSpec[100]));
  404.             if (scanners == NULL) return MemError();
  405.             index = 1;
  406.             do
  407.             {
  408.                 short i;
  409.                 err = GetDirItems(pb.ioFCBVRefNum, ci.dirInfo.ioDrDirID, folderName, true, false, scanners, 100, &actualCount, &index);
  410.                 for (i = 0; i < actualCount; i++)
  411.                 {
  412.                     AppendMenu(menu, "\pgrog");
  413.                     SetMenuItemText(menu, CountMenuItems(menu), scanners[i].name);
  414.                     SetControlMaximum(popup, GetControlMaximum(popup) + 1);
  415.                 }
  416.             } while (err == noErr);
  417.             DisposePtr((Ptr)scanners);
  418.         }
  419.         
  420.         (*status)->popupsInitialized = true;
  421.     }
  422.  
  423.     state = HGetState((Handle)status);
  424.     HLock((Handle)status);
  425.         
  426.     GetDialogItem(dp, baseItems + kScriptIncludeFileItem, &itemType, &itemHand, &itemRect);
  427.     SetDialogItemText(itemHand, (*prefsData)->scriptIncludeFile);
  428.  
  429.     if ((*status)->current < 0)
  430.     {
  431.         // no current extension -- disable all items
  432.         DisableAllItems(dp, baseItems);
  433.         (*status)->enableIncludes = false;
  434.     }
  435.     else
  436.     {
  437.         EnableMainItems(dp, baseItems);
  438.         (*status)->enableIncludes = ((*prefsData)->extensions[(*status)->current].extension[0] != 0);
  439.         if ((*status)->enableIncludes)
  440.             EnableIncludeItems(dp, baseItems);
  441.         else
  442.             DisableIncludeItems(dp, baseItems);
  443.         
  444.         // set up scanner popup menu selection
  445.         {
  446.             Str31 theScanner;
  447.             short i, lim;
  448.             
  449.             GetDialogItem(dp, baseItems + kIncludeScannerItem, &itemType, &itemHand, &itemRect);
  450.             popup = (ControlHandle)itemHand;
  451.             controlData = (*popup)->contrlData;
  452.             popupData = (PopupPrivateDataHandle)controlData;
  453.             menu = (*popupData)->mHandle;
  454.             BlockMoveData((*prefsData)->extensions[(*status)->current].scanner, theScanner,
  455.                           (*prefsData)->extensions[(*status)->current].scanner[0] + 1);
  456.             for (i = 3, lim = CountMenuItems(menu); i <= lim; i++)
  457.             {
  458.                 // if this is the scanner, then select it
  459.                 Str31 thisScanner;
  460.                 GetMenuItemText(menu, i, thisScanner);
  461.                 if (EqualString(thisScanner, theScanner, false, true))
  462.                 {
  463.                     SetControlValue(popup, i);
  464.                     break;
  465.                 }
  466.             }
  467.         }
  468.         
  469.         GetDialogItem(dp, baseItems + kIncludePathItem, &itemType, &itemHand, &itemRect);
  470.         SetDialogItemText(itemHand, (*prefsData)->extensions[(*status)->current].includeFileArg);
  471.         
  472.         GetDialogItem(dp, baseItems + kCommandItem, &itemType, &itemHand, &itemRect);
  473.         SetDialogItemText(itemHand, (*prefsData)->extensions[(*status)->current].commandTemplate);
  474.     }
  475.     
  476.     HSetState((Handle)status, state);
  477.     return noErr;
  478. }
  479.  
  480.  
  481. /*
  482.  *    DialogToOptions        -    copy the options data from screen to the handle
  483.  *
  484.  */
  485.  
  486. static short DialogToOptions(DialogPtr dp, Handle options, short baseItems, void *storage)
  487. {
  488.     ToolFrontEndPanelStatus**    status = (ToolFrontEndPanelStatus**)storage;
  489.     ToolFrontEndPref **            prefsData = (ToolFrontEndPrefHandle) options;
  490.     Handle                        itemHand;
  491.     short                        itemType;
  492.     Rect                        itemRect;
  493.     Str255                        tempStr;
  494.     Byte                        state;
  495.     MenuHandle                    menu;
  496.     ControlHandle                popup;
  497.     Handle                        controlData;
  498.     PopupPrivateDataHandle        popupData;
  499.     
  500.     state = HGetState((Handle)status);
  501.     HLock((Handle)status);
  502.     
  503.     GetDialogItem(dp, baseItems + kScriptIncludeFileItem, &itemType, &itemHand, &itemRect);
  504.     GetDialogItemText(itemHand, tempStr);
  505.     if (StrLength(tempStr) >= sizeof((*prefsData)->scriptIncludeFile))
  506.         tempStr[0] = sizeof((*prefsData)->scriptIncludeFile) - 1;
  507.     BlockMoveData(tempStr, (*prefsData)->scriptIncludeFile, StrLength(tempStr)+1);
  508.     
  509.     if ((*status)->current < 0)
  510.     {
  511.         // no current extension
  512.     }
  513.     else
  514.     {
  515.         // extract data from scanner popup menu
  516.         GetDialogItem(dp, baseItems + kIncludeScannerItem, &itemType, &itemHand, &itemRect);
  517.         popup = (ControlHandle)itemHand;
  518.         controlData = (*popup)->contrlData;
  519.         popupData = (PopupPrivateDataHandle)controlData;
  520.         menu = (*popupData)->mHandle;
  521.         if (GetControlValue(popup) == 1)
  522.         {
  523.             (*prefsData)->extensions[(*status)->current].scanner[0] = 0;
  524.         }
  525.         else
  526.         {
  527.             Str31 scanner;
  528.             GetMenuItemText(menu, GetControlValue(popup), scanner);
  529.             BlockMoveData(scanner, (*prefsData)->extensions[(*status)->current].scanner, StrLength(scanner)+1);
  530.         }
  531.         
  532.         GetDialogItem(dp, baseItems + kIncludePathItem, &itemType, &itemHand, &itemRect);
  533.         GetDialogItemText(itemHand, tempStr);
  534.         if (StrLength(tempStr) >= sizeof((*prefsData)->extensions[(*status)->current].includeFileArg))
  535.             tempStr[0] = sizeof((*prefsData)->extensions[(*status)->current].includeFileArg) - 1;
  536.         BlockMoveData(tempStr, (*prefsData)->extensions[(*status)->current].includeFileArg, StrLength(tempStr)+1);
  537.         
  538.         GetDialogItem(dp, baseItems + kCommandItem, &itemType, &itemHand, &itemRect);
  539.         GetDialogItemText(itemHand, tempStr);
  540.         if (StrLength(tempStr) >= sizeof((*prefsData)->extensions[(*status)->current].commandTemplate))
  541.             tempStr[0] = sizeof((*prefsData)->extensions[(*status)->current].commandTemplate) - 1;
  542.         BlockMoveData(tempStr, (*prefsData)->extensions[(*status)->current].commandTemplate, StrLength(tempStr)+1);
  543.     }
  544.     
  545.     HSetState((Handle)status, state);
  546.  
  547.     return noErr;
  548. }
  549.  
  550. /*
  551.  *    Filter        -    filter an event for the Preferences panel
  552.  *
  553.  */
  554.  
  555. static short Filter(DialogPtr dp, EventRecord *event, short *itemHit, void *storage)
  556. {
  557. #pragma unused(dp, event, itemHit, storage)
  558.     return noErr;
  559. }
  560.  
  561.  
  562. /*
  563.  *    ItemHit        -    handle an itemHit in a Preferences panel
  564.  *
  565.  */
  566.  
  567. static void ItemHit(PanelParameterBlock *pb, void *storage)
  568. {
  569.     ToolFrontEndPanelStatus** status = (ToolFrontEndPanelStatus**)storage;
  570.     ToolFrontEndPref**    current = (ToolFrontEndPrefHandle) pb->currentPrefs;
  571.     ToolFrontEndPref**    original = (ToolFrontEndPrefHandle) pb->originalPrefs;
  572.     ControlHandle        ctrlHand;
  573.     short                itemType;
  574.     Rect                itemRect;
  575.     short                value;
  576.     Handle                itemHand;
  577.     GrafPtr                save;
  578.     
  579.     GetPort(&save);
  580.     SetPort(pb->dialog);
  581.     
  582.     switch (pb->itemHit - pb->baseItems)
  583.     {
  584.     case kExtensionPopupItem:
  585.         GetDialogItem(pb->dialog, pb->itemHit, &itemType, (Handle *) &ctrlHand, &itemRect);
  586.         value = GetControlValue(ctrlHand);
  587.         switch (value)
  588.         {
  589.         case 1:
  590.             // add new extension
  591.             {
  592.                 Str15 extension;
  593.                 Byte state;
  594.                 Size size;
  595.                 
  596.                 // get the menu
  597.                 Handle controlData = (*ctrlHand)->contrlData;
  598.                 PopupPrivateDataHandle popupData = (PopupPrivateDataHandle)controlData;
  599.                 MenuHandle menu = (*popupData)->mHandle;
  600.                 
  601.                 // put up a dialog asking for an extension string
  602.                 if (!GetExtensionString(extension)) break;
  603.                 
  604.                 // XXX search the existing prefs for the string -- no dupes!
  605.                 
  606.                 // add a new entry at the end of the prefs
  607.                 state = HGetState((Handle)current);
  608.                 HLock((Handle)current);
  609.                 size = GetHandleSize((Handle)current);
  610.                 if (state & 0x4)
  611.                     SetResourceSize((Handle)current, size + sizeof(struct ExtensionEntry[1]));
  612.                 else
  613.                     SetHandleSize((Handle)current, size + sizeof(struct ExtensionEntry[1]));
  614.                 BlockMoveData(extension, 
  615.                                 (*current)->extensions[(*current)->numExtensions].extension,
  616.                                 extension[0] + 1);
  617.                 (*current)->extensions[(*current)->numExtensions].includeFileArg[0] = 0;
  618.                 (*current)->extensions[(*current)->numExtensions].scanner[0] = 0;
  619.                 (*current)->extensions[(*current)->numExtensions].commandTemplate[0] = 0;
  620.                 (*current)->numExtensions++;
  621.                 (*current)->scriptIncludeFile[0] = 0;
  622.                 HSetState((Handle)current, state);
  623.  
  624.                 // add a new item at the end of the menu
  625.                 if ((*current)->numExtensions == 1)
  626.                     AppendMenu(menu, "\p(-");
  627.                 AppendMenu(menu, extension);
  628.                 
  629.                 // set the menu item and current status item
  630.                 (*status)->current = (*current)->numExtensions - 1;
  631.                 SetControlMaximum(ctrlHand, (*current)->numExtensions + 3);
  632.                 SetControlValue(ctrlHand, (*current)->numExtensions + 3);
  633.                 
  634.                 // redraw the dialog
  635.                 EnableMainItems(pb->dialog, pb->baseItems);
  636.                 DisableIncludeItems(pb->dialog, pb->baseItems);
  637.                 (*status)->enableIncludes = false;
  638.                 GetDialogItem(pb->dialog, pb->baseItems + kOverallBoxItem, &itemType, &itemHand, &itemRect);
  639.                 InvalRect(&itemRect);
  640.                 OptionsToDialog(pb->dialog, pb->currentPrefs, pb->baseItems, storage);
  641.             }
  642.             break;
  643.             
  644.         case 2:
  645.             // remove current extension
  646.             {
  647.                 Byte state;
  648.                 Size size;
  649.                 
  650.                 // get the menu
  651.                 Handle controlData = (*ctrlHand)->contrlData;
  652.                 PopupPrivateDataHandle popupData = (PopupPrivateDataHandle)controlData;
  653.                 MenuHandle menu = (*popupData)->mHandle;
  654.                 
  655.                 // delete the menu item
  656.                 DeleteMenuItem(menu, value);
  657.                 
  658.                 // shift and resize data in the handle
  659.                 --(*current)->numExtensions;
  660.                 if ((*current)->numExtensions != (*status)->current)
  661.                 {
  662.                     // shift back later entries
  663.                     BlockMoveData((*current)->extensions + (*status)->current + 1,
  664.                                   (*current)->extensions + (*status)->current,
  665.                                   sizeof(struct ExtensionEntry[1])
  666.                                       * ((*current)->numExtensions - (*status)->current));
  667.                 }
  668.                 state = HGetState((Handle)current);
  669.                 size = GetHandleSize((Handle)current);
  670.                 if (state & 0x4)
  671.                     SetResourceSize((Handle)current, size - sizeof(struct ExtensionEntry[1]));
  672.                 else
  673.                     SetHandleSize((Handle)current, size - sizeof(struct ExtensionEntry[1]));
  674.                 
  675.                 // set the menu item and current status item
  676.                 if ((*current)->numExtensions == 0)
  677.                 {
  678.                     // last one went away
  679.                     DeleteMenuItem(menu, 3);    // delete separator
  680.                     DisableItem(menu, 2);        // delete remove item
  681.                     SetControlValue(ctrlHand, 1);
  682.                     (*status)->current = -1;
  683.                     
  684.                     // redraw the dialog
  685.                     DisableAllItems(pb->dialog, pb->baseItems);
  686.                     GetDialogItem(pb->dialog, pb->baseItems + kOverallBoxItem, &itemType, &itemHand, &itemRect);
  687.                     InvalRect(&itemRect);
  688.                 }
  689.                 else
  690.                 {
  691.                     (*status)->current = 0;        // select first item
  692.                     SetControlValue(ctrlHand, 4);
  693.                     
  694.                     // redraw the dialog
  695.                     (*status)->enableIncludes = ((*current)->extensions[(*status)->current].scanner[0] != 0);
  696.                     if ((*status)->enableIncludes)
  697.                         EnableIncludeItems(pb->dialog, pb->baseItems);
  698.                     else
  699.                         DisableIncludeItems(pb->dialog, pb->baseItems);
  700.                     GetDialogItem(pb->dialog, pb->baseItems + kOverallBoxItem, &itemType, &itemHand, &itemRect);
  701.                     InvalRect(&itemRect);
  702.                 }
  703.                 
  704.                 OptionsToDialog(pb->dialog, pb->currentPrefs, pb->baseItems, storage);
  705.             }
  706.             break;
  707.             
  708.         default:
  709.             // select current extension
  710.             DialogToOptions(pb->dialog, pb->currentPrefs, pb->baseItems, storage);
  711.             (*status)->current = value - 4;
  712.             
  713.             // redraw the dialog
  714.             (*status)->enableIncludes = ((*current)->extensions[(*status)->current].scanner[0] != 0);
  715.             if ((*status)->enableIncludes)
  716.                 EnableIncludeItems(pb->dialog, pb->baseItems);
  717.             else
  718.                 DisableIncludeItems(pb->dialog, pb->baseItems);
  719.             GetDialogItem(pb->dialog, pb->baseItems + kOverallBoxItem, &itemType, &itemHand, &itemRect);
  720.             InvalRect(&itemRect);
  721.             OptionsToDialog(pb->dialog, pb->currentPrefs, pb->baseItems, storage);
  722.             break;
  723.         }
  724.         break;
  725.  
  726.     default:
  727.         DialogToOptions(pb->dialog, pb->currentPrefs, pb->baseItems, storage);
  728.         break;
  729.     }
  730.     
  731.     
  732.     pb->canRevert    = !ComparePrefs(pb->originalPrefs, pb->currentPrefs);
  733.     pb->canFactory    = !ComparePrefs(pb->factoryPrefs,  pb->currentPrefs);
  734.     
  735.     SetPort(save);
  736. }
  737.  
  738. /*
  739.  *    Validate    -    check if panel's changes require a recompile or relink
  740.  *
  741.  */
  742.  
  743. static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset)
  744. {
  745. #pragma unused(original, current)
  746.     
  747.     // XXX Validate
  748.     *recompile    = false;
  749.     *relink        = false;
  750.     *reset        = false;
  751. }
  752.  
  753. /*
  754.  *    GetPref        -    get a specified Preference setting for an AppleEvent request
  755.  *
  756.  */
  757.  
  758. static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings)
  759. {
  760.     ToolFrontEndPref    prefsData    = ** (ToolFrontEndPrefHandle) settings;
  761.     DescType    anEnum;
  762.     OSErr        err;
  763.     
  764.     switch (keyword)
  765.     {
  766.     // XXX get a specified Preference setting for an AppleEvent request
  767. #if 0
  768.     case prefsLN_GenerateSymFile:
  769.         err = AECreateDesc(typeBoolean, &(*prefsData)->extensions[(*status)->current].linksym, sizeof(Boolean), prefsDesc);
  770.         break;
  771.         
  772.     case prefsPR_ProjectType:
  773.         switch ((*prefsData)->extensions[(*status)->current].projtype)
  774.         {
  775.         case kProjTypeApplication:    anEnum = enum_Project_Application;        break;
  776.         case kProjTypeLibrary:        anEnum = enum_Project_Library;            break;
  777.         case kProjTypeSharedLib:    anEnum = enum_Project_SharedLibrary;    break;
  778.         case kProjTypeCodeResource:    anEnum = enum_Project_CodeResource;        break;
  779.         case kProjTypeMPWTool:        anEnum = enum_Project_MPWTool;            break;
  780.         default:                    return (paramErr);
  781.         }
  782.         err = AECreateDesc(typeEnumeration, &anEnum, sizeof(anEnum), prefsDesc);
  783.         break;
  784.         
  785.     case prefsPR_FileName:
  786.         err = AECreateDesc(typeChar, (*prefsData)->extensions[(*status)->current].outfile+1, StrLength((*prefsData)->extensions[(*status)->current].outfile), prefsDesc);
  787.         break;
  788. #endif
  789.  
  790.     default:
  791.         err = errAECantHandleClass;
  792.         break;
  793.     }
  794.     
  795.     return (err);
  796. }
  797.  
  798. /*
  799.  *    SetPref        -    set a specified Preference setting from an AppleEvent request
  800.  *
  801.  */
  802.  
  803. static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings)
  804. {
  805.     ToolFrontEndPref    prefsData    = ** (ToolFrontEndPrefHandle) settings;
  806.     AEDesc            toDesc    = { typeNull, NULL };
  807.     OSErr            err        = noErr;
  808.     Handle            dataHand;
  809.     Size            textLength;
  810.     DescType        anEnum;
  811.     
  812.     switch (keyword)
  813.     {
  814.     // XXX set a specified Preference setting from an AppleEvent request
  815. #if 0
  816.     case prefsLN_GenerateSymFile:
  817.         if (prefsDesc->descriptorType == typeBoolean)
  818.         {
  819.             dataHand = prefsDesc->dataHandle;
  820.         }
  821.         else
  822.         {
  823.             err = AECoerceDesc(prefsDesc, typeBoolean, &toDesc);
  824.             if (err == noErr)
  825.                 dataHand = toDesc.dataHandle;
  826.         }
  827.         if (err == noErr)
  828.         {
  829.             (*prefsData)->extensions[(*status)->current].linksym = ** (Boolean **) dataHand;
  830.         }
  831.         break;
  832.         
  833.     case prefsPR_ProjectType:
  834.         if (prefsDesc->descriptorType != typeEnumeration)
  835.         {
  836.             err = errAETypeError;
  837.             break;
  838.         }
  839.  
  840.         anEnum = ** (DescType **) prefsDesc->dataHandle;
  841.         
  842.         switch (anEnum)
  843.         {
  844.         case enum_Project_Application:        (*prefsData)->extensions[(*status)->current].projtype = kProjTypeApplication;    break;
  845.         case enum_Project_Library:            (*prefsData)->extensions[(*status)->current].projtype = kProjTypeLibrary;        break;
  846.         case enum_Project_SharedLibrary:    (*prefsData)->extensions[(*status)->current].projtype = kProjTypeSharedLib;    break;
  847.         case enum_Project_CodeResource:        (*prefsData)->extensions[(*status)->current].projtype = kProjTypeCodeResource;    break;
  848.         case enum_Project_MPWTool:            (*prefsData)->extensions[(*status)->current].projtype = kProjTypeMPWTool;        break;
  849.         default:                            return (errAECoercionFail);
  850.         }
  851.         break;
  852.         
  853.     case prefsPR_FileName:
  854.         if (prefsDesc->descriptorType == typeChar)
  855.         {
  856.             dataHand = prefsDesc->dataHandle;
  857.         }
  858.         else
  859.         {
  860.             err = AECoerceDesc(prefsDesc, typeChar, &toDesc);
  861.             if (err == noErr)
  862.                 dataHand = toDesc.dataHandle;
  863.         }
  864.         if (err == noErr)
  865.         {
  866.             textLength = GetHandleSize(dataHand);
  867.             if (textLength > sizeof((*prefsData)->extensions[(*status)->current].outfile) - 1)
  868.                 textLength = sizeof((*prefsData)->extensions[(*status)->current].outfile) - 1;
  869.             BlockMoveData(*dataHand, (*prefsData)->extensions[(*status)->current].outfile+1, textLength);
  870.             (*prefsData)->extensions[(*status)->current].outfile[0] = textLength;
  871.         }
  872.         break;
  873. #endif
  874.  
  875.     default:
  876.         err = errAECantHandleClass;
  877.         break;
  878.     }
  879.     
  880.     if (err == noErr)
  881.     {
  882.         ** (ToolFrontEndPrefHandle) settings = prefsData;
  883.     }
  884.     
  885.     AEDisposeDesc(&toDesc);
  886.     
  887.     return (err);
  888. }
  889.  
  890. /*
  891.  *    GetFactory    -    retrieve factory settings
  892.  *
  893.  */
  894.  
  895. static short GetFactory(Handle settings, DialogPtr dp)
  896. {
  897. #pragma unused(dp)
  898.  
  899.     OSErr err;
  900.     SetHandleSize(settings, sizeof(ToolFrontEndPref));
  901.     err = MemError();
  902.     if (err == noErr)
  903.     {
  904.         int i;
  905.         char *c;
  906.         
  907.         for (i = sizeof(ToolFrontEndPref), c = (char*)*settings; i > 0; i--)
  908.             *c++ = 0;
  909.     }
  910.     return (err);
  911. }
  912.  
  913. /*
  914.  *    UpdatePref    -    "upgrade" a pref to the current version
  915.  *
  916.  */
  917.  
  918. static short UpdatePref(Handle settings)
  919. {
  920.     ToolFrontEndPrefHandle    prefsHand    = (ToolFrontEndPrefHandle) settings;
  921.     OSErr err = noErr;
  922.     
  923.     switch ((*prefsHand)->version)
  924.     {
  925.     case PTOOLFRONTENDVERSION:
  926.         break;
  927.     default:
  928.         err = kBadPrefVersion;
  929.         break;
  930.     }
  931.     
  932.     return (err);
  933. }
  934.  
  935.  
  936. static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2)
  937. {
  938.     ToolFrontEndPrefHandle    prefs1    = (ToolFrontEndPrefHandle) prefsHand1;
  939.     ToolFrontEndPrefHandle    prefs2    = (ToolFrontEndPrefHandle) prefsHand2;
  940.     Boolean differ = false;
  941.     Byte state1, state2;
  942.     
  943.     state1 = HGetState(prefsHand1);
  944.     HLock(prefsHand1);
  945.     state2 = HGetState(prefsHand2);
  946.     HLock(prefsHand2);
  947.     
  948.     if ((*prefs1)->numExtensions != (*prefs2)->numExtensions)
  949.     {
  950.         differ = true;
  951.     }
  952.     else
  953.     {
  954.         int i;
  955.         differ = EqualString((*prefs1)->scriptIncludeFile, (*prefs2)->scriptIncludeFile, false, true);
  956.         for (i = 0; !differ && i < (*prefs1)->numExtensions; i++)
  957.         {
  958.             differ = (    EqualString((*prefs1)->extensions[i].extension, (*prefs2)->extensions[i].extension, false, true)
  959.                     &&  EqualString((*prefs1)->extensions[i].scanner, (*prefs2)->extensions[i].scanner, false, true)
  960.                     &&  EqualString((*prefs1)->extensions[i].includeFileArg, (*prefs2)->extensions[i].includeFileArg, false, true)
  961.                     &&  EqualString((*prefs1)->extensions[i].commandTemplate, (*prefs2)->extensions[i].commandTemplate, false, true));
  962.         }
  963.     }
  964.     
  965.     HSetState(prefsHand1, state1);
  966.     HSetState(prefsHand2, state2);
  967.     
  968.     return !differ;
  969. }
  970.  
  971.  
  972. void EnableMainItems(DialogPtr dp, short baseItems)
  973. {
  974.     ControlHandle        ctrlHand;
  975.     short                itemType;
  976.     Rect                itemRect;
  977.     Handle                itemHand;
  978.     
  979.     GetDialogItem(dp, baseItems + kIncludeScannerItem, &itemType, (Handle*)&ctrlHand, &itemRect);
  980.     HiliteControl(ctrlHand, 0);
  981.     GetDialogItem(dp, baseItems + kCommandItem, &itemType, &itemHand, &itemRect);
  982.     SetDialogItem(dp, baseItems + kCommandItem, editText, itemHand, &itemRect);
  983.     FixEditField(dp);
  984. }
  985.  
  986.  
  987. void EnableIncludeItems(DialogPtr dp, short baseItems)
  988. {
  989.     ControlHandle        ctrlHand;
  990.     short                itemType;
  991.     Rect                itemRect;
  992.     Handle                itemHand;
  993.     
  994.     GetDialogItem(dp, baseItems + kIncludeScannerItem, &itemType, (Handle*)&ctrlHand, &itemRect);
  995.     HiliteControl(ctrlHand, 0);
  996.     GetDialogItem(dp, baseItems + kIncludePathItem, &itemType, &itemHand, &itemRect);
  997.     SetDialogItem(dp, baseItems + kIncludePathItem, editText, itemHand, &itemRect);
  998.     FixEditField(dp);
  999. }
  1000.  
  1001.  
  1002. void DisableAllItems(DialogPtr dp, short baseItems)
  1003. {
  1004.     short                itemType;
  1005.     Rect                itemRect;
  1006.     Handle                itemHand;
  1007.     
  1008.     GetDialogItem(dp, baseItems + kCommandItem, &itemType, &itemHand, &itemRect);
  1009.     SetDialogItem(dp, baseItems + kCommandItem, statText + itemDisable, itemHand, &itemRect);
  1010.     DisableIncludeItems(dp, baseItems);
  1011.     FixEditField(dp);
  1012. }
  1013.  
  1014.  
  1015. void DisableIncludeItems(DialogPtr dp, short baseItems)
  1016. {
  1017.     ControlHandle        ctrlHand;
  1018.     short                itemType;
  1019.     Rect                itemRect;
  1020.     Handle                itemHand;
  1021.     
  1022.     GetDialogItem(dp, baseItems + kIncludeScannerItem, &itemType, (Handle*)&ctrlHand, &itemRect);
  1023.     HiliteControl(ctrlHand, 255);
  1024.     GetDialogItem(dp, baseItems + kIncludePathItem, &itemType, &itemHand, &itemRect);
  1025.     SetDialogItem(dp, baseItems + kIncludePathItem, statText + itemDisable, itemHand, &itemRect);
  1026.     FixEditField(dp);
  1027. }
  1028.  
  1029.  
  1030. void FixEditField(DialogPtr dp)
  1031. {
  1032.     DialogPeek peek = (DialogPeek)dp;
  1033.     short                itemType;
  1034.     Rect                itemRect;
  1035.     Handle                itemHand;
  1036.     short                editItem = peek->editField + 1;
  1037.     
  1038.     if (editItem > 0)
  1039.     {
  1040.         // verify that the item deserves the kleyboard focus; if not, go somewhere else
  1041.         GetDialogItem(dp, editItem, &itemType, &itemHand, &itemRect);
  1042.         if (itemType != editText)
  1043.         {
  1044.             int i, lim;
  1045.             Boolean found = false;
  1046.             
  1047.             SelectDialogItemText(dp, editItem, 0, 0);
  1048.             for (i = 1, lim = CountDITL(dp); i <= lim; i++)
  1049.             {
  1050.                 GetDialogItem(dp, editItem, &itemType, &itemHand, &itemRect);
  1051.                 if (itemType == editText)
  1052.                 {
  1053.                     SelectDialogItemText(dp, i, 0, 32767);
  1054.                     found = true;
  1055.                     break;
  1056.                 }
  1057.             }
  1058.             if (!found)
  1059.             {
  1060.                 // there are no edit text items
  1061.                 peek->editField = -1;
  1062.             }
  1063.         }
  1064.     }
  1065.     else
  1066.     {
  1067.         // no keyboard focus -- see if there should be one
  1068.         int i, lim;
  1069.         for (i = 1, lim = CountDITL(dp); i <= lim; i++)
  1070.         {
  1071.             GetDialogItem(dp, editItem, &itemType, &itemHand, &itemRect);
  1072.             if (itemType == editText)
  1073.             {
  1074.                 SelectDialogItemText(dp, i, 0, 32767);
  1075.                 break;
  1076.             }
  1077.         }
  1078.     }
  1079. }
  1080.  
  1081.  
  1082. Boolean    GetExtensionString(StringPtr extension)
  1083. {
  1084.     short                itemHit;
  1085.     short                itemType;
  1086.     Rect                itemRect;
  1087.     Handle                itemHand;
  1088.     Boolean                done, result;
  1089.     
  1090.     DialogPtr dialog = GetNewDialog(kGetExtensionDialog, NULL, (WindowPtr)-1);
  1091.     SelectDialogItemText(dialog, kExtensionTextItem, 0, 32767);
  1092.     done = false;
  1093.     do
  1094.     {
  1095.         ModalDialog(NULL, &itemHit);
  1096.         switch (itemHit)
  1097.         {
  1098.         case ok:
  1099.             GetDialogItem(dialog, kExtensionTextItem, &itemType, &itemHand, &itemRect);
  1100.             GetDialogItemText(itemHand, extension);
  1101.             result = true;
  1102.             done = true;
  1103.             break;
  1104.         case cancel:
  1105.             result = false;
  1106.             done = true;
  1107.             break;
  1108.         }
  1109.     } while (!done);
  1110.     DisposeDialog(dialog);
  1111.         
  1112.     return result;
  1113. }
  1114.